//
//  Codable+Ex.swift
//  aquariumstudio
//
//  Created by zj on 2022/10/21.
//  Copyright © 2022 LXF. All rights reserved.
//

import Foundation

public class CodableEx{
    
    public static func copy<T>(_ value: T)->T? where T : Codable{
        
        guard let json = try? JSONEncoder.encode(value)else{
            return nil
        }
        let t = try? JSONDecoder.decode(T.self, from: json)
        
        return t
    }
    
    
    public static func encoder<T: Encodable>(toDictionary model:T) -> [String:Any?]? {
    
        let encoder = JSONEncoder()

        encoder.outputFormatting = .prettyPrinted

        guard let data = try? encoder.encode(model) else {
            return nil
        }

        guard let dict = try?JSONSerialization.jsonObject(with: data, options: .mutableLeaves) as? [String:Any?] else{
            return nil
        }
        return dict

    }

    
}

public extension JSONDecoder{
    
    /// 📢  Decodes a top-level value of the given type from the given JSON representation.
    /// 从给定的JSON表示中解码给定类型的顶级值。
    /// - parameter type: The type of the value to decode.
    /// - parameter data: The data to decode from.
    /// - returns: A value of the requested type.
    /// - throws: `DecodingError.dataCorrupted` if values requested from the payload are corrupted, or if the given data is not valid JSON.
    /// - throws: An error if any value throws an error during decoding.
    static func decode<T>(_ type: T.Type, from jsonStr: String) throws -> T where T : Decodable{
        
        guard let jsondata = jsonStr.data(using: String.Encoding.utf8) else {
            throw NSError.init(domain: "解析 json 失败", code: 999)
        }
        let decode = JSONDecoder.init()
        let obj = try decode.decode(type, from: jsondata)
        
        return obj
    }
}

public extension JSONEncoder{
    /// 📢 Encodes the given top-level value and returns its JSON representation.
    /// 编码给定的顶层值并返回其JSON表示。
    /// - parameter value: The value to encode.
    /// - returns: A new `Data` value containing the encoded JSON data.
    /// - throws: `EncodingError.invalidValue` if a non-conforming floating-point value is encountered during encoding, and the encoding strategy is `.throw`.
    /// - throws: An error if any value throws an error during encoding.
    static func encode<T>(_ value: T) throws -> String where T : Encodable{
        let jsondata = try JSONEncoder().encode(value)
//        guard let jsondata1 = jsondata else {
//            throw NSError.init(domain: "转 json 失败", code: 999)
//        }
        let jsonStr = String.init(decoding: jsondata, as: UTF8.self)
        return jsonStr
        
    }
}
